package com.whfc.safety.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.exception.BizException;
import com.whfc.common.generator.KeyGeneratorUtil;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.PageUtil;
import com.whfc.common.util.RegexUtil;
import com.whfc.safety.dao.SafetyIssueMapper;
import com.whfc.safety.dao.SafetyIssueTypeMapper;
import com.whfc.safety.dto.SafetyIssueDTO;
import com.whfc.safety.dto.SafetyIssueTypeDTO;
import com.whfc.safety.entity.SafetyIssue;
import com.whfc.safety.entity.SafetyIssueType;
import com.whfc.safety.param.SafetyIssueAddParam;
import com.whfc.safety.param.SafetyIssueEditParam;
import com.whfc.safety.param.SafetyIssueTypeAddParam;
import com.whfc.safety.param.SafetyIssueTypeEditParam;
import com.whfc.safety.service.SafetyIssueService;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClasssName SafetyIssueServiceImpl
 * @Description 安全问题类型/明细接实现类
 * @Author hw
 * @Date 2020/8/5 14:38
 * @Version 1.0
 */
@DubboService(interfaceClass = SafetyIssueService.class, version = "1.0.0", timeout = 5000)
public class SafetyIssueServiceImpl implements SafetyIssueService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SafetyIssueMapper safetyIssueMapper;

    @Autowired
    private SafetyIssueTypeMapper safetyIssueTypeMapper;

    @Override
    public List<SafetyIssueTypeDTO> issueTypeList(Integer deptId, String keyword) throws BizException {
        logger.info("查询安全问题类别，deptId:{},keyword:{}", deptId, keyword);
        List<SafetyIssueTypeDTO> issueTypeList = safetyIssueTypeMapper.selectIssueTypeList(deptId, keyword);
        List<SafetyIssueDTO> issueList = safetyIssueMapper.selectByDeptId(deptId);
        return parseTree(issueTypeList, issueList);
    }

    @Override
    public void addIssueType(SafetyIssueTypeAddParam addParam) throws BizException {
        logger.info("新增安全问题类别，SafetyIssueTypeAddParam:{}", addParam);
        SafetyIssueType issueType = new SafetyIssueType();
        String code = addParam.getCode();
        if (!RegexUtil.isInteger(code)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "编码格式错误.");
        }

        if (addParam.getPid() != null) {
            SafetyIssueType pIssueType = safetyIssueTypeMapper.selectByPrimaryKey(addParam.getPid());
            if (pIssueType == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "父问题类型节点不存在");
            }
            if (!safetyIssueMapper.selectByIssueTypeId(addParam.getPid()).isEmpty()) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "父问题类型节点下已存在数据不能添加子节点");
            }
            code = pIssueType.getCode() + "." + code;
            issueType.setPid(pIssueType.getId());
            issueType.setLevel(pIssueType.getLevel() + 1);
        } else {
            issueType.setPid(0L);
            issueType.setLevel(1);
        }
        Integer deptId = addParam.getDeptId();
        if (safetyIssueTypeMapper.selectIssueTypeByCode(deptId, code) != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该编码已存在.");
        }
        issueType.setId(KeyGeneratorUtil.genLongId());
        issueType.setDeptId(deptId);
        issueType.setCode(code);
        issueType.setName(addParam.getName());
        safetyIssueTypeMapper.insertSelective(issueType);
    }

    @Override
    public void editIssueType(SafetyIssueTypeEditParam editParam) throws BizException {
        logger.info("修改安全问题类别，SafetyIssueTypeEditParam:{}", editParam);
        String code = editParam.getCode();
        if (!RegexUtil.isInteger(code)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "编码格式错误.");
        }
        SafetyIssueType safetyIssueType = safetyIssueTypeMapper.selectByPrimaryKey(editParam.getIssueTypeId());
        if (safetyIssueType == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该问题类型不存在.");
        }

        SafetyIssueType pIssueType = safetyIssueTypeMapper.selectByPrimaryKey(safetyIssueType.getPid());
        if (pIssueType != null) {
            code = pIssueType.getCode() + "." + code;
        }
        if (safetyIssueTypeMapper.selectIssueTypeByCode(safetyIssueType.getDeptId(), code) != null
                && !safetyIssueType.getCode().equals(code)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该编码已存在.");
        }
        Integer length = safetyIssueType.getCode().length();
        List<SafetyIssueType> issueTypes = safetyIssueTypeMapper.selectLikeCode(safetyIssueType.getCode() + ".");
        for (SafetyIssueType issueType : issueTypes) {
            issueType.setCode(code + issueType.getCode().substring(length));
            safetyIssueTypeMapper.updateByPrimaryKeySelective(issueType);
        }
        safetyIssueTypeMapper.updateById(editParam.getIssueTypeId(), code, editParam.getName());
    }

    @Override
    public void delIssueType(Long issueTypeId) throws BizException {
        logger.info("删除安全问题类别，issueTypeId:{}", issueTypeId);
        List<SafetyIssueType> issueType = safetyIssueTypeMapper.selectByPid(issueTypeId);
        List<SafetyIssueDTO> issues = safetyIssueMapper.selectByIssueTypeId(issueTypeId);
        if (!issueType.isEmpty() || !issues.isEmpty()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "有子节点存在无法删除.");
        }
        safetyIssueTypeMapper.logicDel(issueTypeId);
    }

    @Override
    public List<SafetyIssueDTO> issueList(Long issueTypeId) throws BizException {
        logger.info("查询安全问题明细，issueTypeId:{}", issueTypeId);
        return safetyIssueMapper.selectByIssueTypeId(issueTypeId);
    }

    @Override
    public PageData<SafetyIssueDTO> issueList(Long issueTypeId, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("查询安全问题明细(分页)，issueTypeId:{},pageNum:{},pageSize:{}", issueTypeId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyIssueDTO> list = safetyIssueMapper.selectByIssueTypeId(issueTypeId);
        if (list == null) {
            return new PageData<>();
        }
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public List<SafetyIssueDTO> issueHistoryList(Integer deptId, Integer pageSize) throws BizException {
        return safetyIssueMapper.selectHistoryByDeptIdAndPageSize(deptId, pageSize);
    }

    @Override
    public void addIssue(SafetyIssueAddParam addParam) throws BizException {
        logger.info("添加安全问题明细，SafetyIssueAddParam：{}", addParam);
        SafetyIssueType issueType = safetyIssueTypeMapper.selectByPrimaryKey(addParam.getIssueTypeId());
        if (issueType == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该问题类型不存在.");
        }
        List<SafetyIssueType> issueTypes = safetyIssueTypeMapper.selectByPid(issueType.getId());
        if (!issueTypes.isEmpty()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该问题类型下存在子节点无法添加明细.");
        }
        SafetyIssue issue = new SafetyIssue();
        BeanUtils.copyProperties(addParam, issue);
        issue.setIssueTypeName(issueType.getName());
        issue.setId(KeyGeneratorUtil.genLongId());
        issue.setDeptId(issueType.getDeptId());
        safetyIssueMapper.insertSelective(issue);
    }

    @Override
    public void editIssue(SafetyIssueEditParam editParam) throws BizException {
        logger.info("修改安全问题明细，SafetyIssueEditParam：{}", editParam);
        if (safetyIssueMapper.selectByPrimaryKey(editParam.getIssueId()) == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该问题明细不存在.");
        }
        safetyIssueMapper.updateByIssueId(editParam.getIssueId(), editParam.getContent(), editParam.getRequire(), editParam.getDuration());
    }

    @Override
    public void delIssue(Long issueId) throws BizException {
        logger.info("删除安全问题明细，issueId：{}", issueId);
        safetyIssueMapper.logicDel(issueId);
    }

    @Override
    public void disableOrEnabledIssue(Long issueId, Integer enable) {
        logger.info("启用/禁用安全问题明细，issueId：{},enable:{}", issueId, enable);
        safetyIssueMapper.disableOrEnabledIssue(issueId, enable);
    }

    @Override
    public List<SafetyIssueDTO> issueList(Integer deptId) throws BizException {
        return safetyIssueMapper.selectByDeptId(deptId);
    }

    @Override
    public void deleteBatch(List<Integer> idList) {
        if(CollectionUtils.isEmpty(idList)){
            return;
        }
        safetyIssueMapper.deleteBatch(idList);
    }

    /**
     * 树形处理数据
     *
     * @param list 问题类型列表
     * @return 问题类型列表
     */
    private List<SafetyIssueTypeDTO> parseTree(List<SafetyIssueTypeDTO> list, List<SafetyIssueDTO> issueDTOS) {
        Map<Long, List<SafetyIssueDTO>> issueDTOMap = new HashMap<>();
        issueDTOS.forEach(issueDTO -> {
            List<SafetyIssueDTO> qualityIssueDTOS;
            if (!issueDTOMap.containsKey(issueDTO.getIssueTypeId())) {
                qualityIssueDTOS = new ArrayList<>();
            } else {
                qualityIssueDTOS = issueDTOMap.get(issueDTO.getIssueTypeId());
            }
            qualityIssueDTOS.add(issueDTO);
            issueDTOMap.put(issueDTO.getIssueTypeId(), qualityIssueDTOS);
        });
        list.forEach(issueTypeDTO -> {
            if (issueDTOMap.containsKey(issueTypeDTO.getIssueTypeId())) {
                issueTypeDTO.setIssues(issueDTOMap.get(issueTypeDTO.getIssueTypeId()));
            }
        });
        Map<Long, List<SafetyIssueTypeDTO>> issueTypeMap = list.stream().collect(Collectors.groupingBy(SafetyIssueTypeDTO::getPid));
        list.forEach(issuetypeDTO -> issuetypeDTO.setChildren(issueTypeMap.get(issuetypeDTO.getIssueTypeId())));
        List<SafetyIssueTypeDTO> result = list.stream().filter(v -> v.getPid().equals(0L)).collect(Collectors.toList());

        return result;
    }
}
